package de.ubschmidt.capi;

import java.nio.ByteBuffer;

/**
 * This message indicates an incoming call for a physical connection. The
 * incoming call is assigned a PLCI which is used to identify this
 * connection in subsequent messages.
 *
 * <p>Incoming calls are only signaled if the application has sent the
 * message LISTEN_REQ to COMMON-ISDN-API.
 *
 * <p>All information available from the network at this point is signaled
 * to the application. Empty structs indicate the absence of this information.
 *
 * <p>Incoming calls are not signaled for security reason if the combination of
 * Calling party number, Calling party subaddress and CIP Value is not
 * allowed by Call Control Supervision (see Annex D.2).
 */
public class ConnectInd
        extends CapiPassiveMessage
        implements CalledPartyNumberAccessor, PlciAccessor {

    private static final int OFFSET_PLCI = OFFSET_MESSAGE;
    private static final int OFFSET_CIP = OFFSET_PLCI + SIZE_OF_PLCI;
    private static final int OFFSET_STRUCTS = OFFSET_CIP + 2;

    /**
     *
     * @param byteBuffer
     */
    public ConnectInd(final ByteBuffer byteBuffer) {
        super(byteBuffer);
    }

    /** {@inheritDoc} */
    public int getPlci() {
        return getByteBuffer().getInt(OFFSET_PLCI);
    }

    /**
     * Retrieve the CIP.
     *
     * @return The CIP.
     */
    public Cip getCip() {
        return Cip.valueOf(getByteBuffer().getShort(OFFSET_CIP));
    }

    /** {@inheritDoc} */
    public CalledPartyNumber getCalledPartyNumber() {
        return new CalledPartyNumber(getByteBufferAtStruct(0));
    }

    /**
     * Retrieve the calling party number.
     *
     * @return The calling party number.
     */
    public CallingPartyNumber getCallingPartyNumber() {
        return new CallingPartyNumber(getByteBufferAtStruct(1));
    }

    /**
     * Retrieve the called party subaddress.
     *
     * @return The called party subaddress.
     */
    public SubAddress getCalledPartySubAddress() {
        return new SubAddress(getByteBufferAtStruct(2));
    }

    /**
     * Retrieve the calling party subaddress.
     *
     * @return The calling party subaddress.
     */
    public SubAddress getCallingPartySubAddress() {
        return new SubAddress(getByteBufferAtStruct(3));
    }

    private ByteBuffer getByteBufferAtStruct(final int position) {
        ByteBuffer byteBuffer = getByteBuffer();
        byteBuffer.position(OFFSET_STRUCTS);

        for (int i = 0; i < position; ++i) {
            CapiStruct.skipStruct(byteBuffer);
        }

        return byteBuffer;
    }

    /** {@inheritDoc} */
    @Override
    public String toString() {
        String s = String.format(
                "%s[%s plci=0x%08x cip=%s called#=%s calling#=%s "
                + "calledSub#=%s callingSub#=%s ...]",
                getClass().getSimpleName(),
                super.toString(),
                getPlci(),
                getCip(),
                getCalledPartyNumber(),
                getCallingPartyNumber(),
                getCalledPartySubAddress(),
                getCallingPartySubAddress());

        for (int i = 0; i < getByteBuffer().limit(); ++i) {
            s += String.format("0x%02x ", getByteBuffer().get(i));
        }

        return s;
    }

}
